<template>
  <a-space direction="vertical" style="width: 100%">
    <a-flex gap="small" wrap="wrap" align="end">
      <a-card :title="sku.name" :key="index" v-for="(sku, index) in skus">
        <template #extra
          ><a-button
            type="primary"
            :icon="h(DeleteOutlined)"
            size="small"
            @click="removeSku(index)"
        /></template>
        <a-flex wrap="wrap" gap="small">
          <template v-for="tag in sku.item" :key="tag">
            <a-tooltip :title="tag">
              <a-tag :closable="true" @close="handleClose(sku, tag)">
                {{ tag.length > 20 ? `${tag.slice(0, 20)}...` : tag }}
              </a-tag>
            </a-tooltip>
          </template>
          <a-input
            v-if="sku.inputVisible"
            v-model:value="sku.inputValue"
            type="text"
            size="small"
            :style="{ width: '78px' }"
            @keyup.enter="handleInputConfirm(sku)"
            @blur="handleInputConfirm(sku)"
            v-focus
          />
          <a-tag v-else style="background: #fff; border-style: dashed" @click="showInput(sku)">
            <plus-outlined />
            添加新属性
          </a-tag>
        </a-flex>
      </a-card>
      <a-button
        v-if="showAddSkuButton"
        type="primary"
        :icon="h(PlusOutlined)"
        @click="hideAddSkuButtonFunc"
        >添加新规格</a-button
      >
      <a-input
        v-else
        size="small"
        style="width: 150px"
        @blur="addNewSku"
        @keyup.enter="addNewSku"
        @keydown.esc="showAddSkuButtonFunc"
        placeholder="请输入"
        allowClear
        v-focus
      />
    </a-flex>
    {{ dataSource }}
    <a-table :columns="columnsRef" :data-source="dataSource" bordered :pagination="false">
      <template #bodyCell="{ column, record }">
        <template v-if="['costPrice', 'linePrice', 'stock'].includes(column.dataIndex)">
          <a-input-number v-model:value="record[column.dataIndex]" style="margin: -5px 0" />
        </template>
        <template v-if="['description'].includes(column.dataIndex)">
          <a-textarea v-model:value="record[column.dataIndex]" show-count :maxlength="100" />
        </template>
        <template v-if="['warnStock'].includes(column.dataIndex)">
          <a-switch v-model:checked="record[column.dataIndex]" />
        </template>
        <template v-if="['status'].includes(column.dataIndex)">
          <a-radio-group v-model:value="record[column.dataIndex]" button-style="solid">
            <a-radio-button value="ON_SHELVES">上架</a-radio-button>
            <a-radio-button value="DELISTED">下架</a-radio-button>
          </a-radio-group>
        </template>
        <template v-if="['skuCode'].includes(column.dataIndex)">
          <a-input v-model:value="record[column.dataIndex]" style="margin: -5px 0" />
        </template>
        <template v-if="['image'].includes(column.dataIndex)">
          <a-upload
            v-model:file-list="record[column.dataIndex]"
            list-type="picture-card"
            :max-count="1"
            action="http://127.0.0.1:20020/file-server/file/upload?bucket=bosi-mall-app-web&path=goods,image"
          >
            <div>
              <plus-outlined />
              <div style="margin-top: 8px">Upload</div>
            </div>
          </a-upload>
        </template>
      </template>
    </a-table>
  </a-space>
</template>
<script lang="ts" setup>
  import { h, reactive, ref, toRaw } from 'vue';
  import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
  import { buildUUID } from '@/utils/uuid';
  import { watchDeep } from '@vueuse/core';
  import { UploadCallBack } from '#/global';

  const showAddSkuButton = ref<boolean>(true);

  interface Sku {
    name: string;
    key: string;
    item: string[];
  }

  interface SkuControl extends Sku {
    inputVisible: boolean;
    inputValue: string;
  }

  const skus = reactive<SkuControl[]>([]);

  // sku基础操作-----------------------------------------------------------------------------------------------
  // 删除一个sku项
  function removeSku(index: number) {
    skus.splice(index, 1);
    columnsRef.value.splice(index, 1);
  }
  // 添加一个sku项
  function addNewSku(value) {
    if (!value.target.value) {
      showAddSkuButtonFunc();
      return;
    }
    let find = skus.find((sku) => {
      return sku.name === value.target.value;
    });
    if (find) {
      return;
    }
    let uuid = buildUUID();
    skus.push({
      name: value.target.value,
      key: uuid,
      item: [],
      inputVisible: false,
      inputValue: '',
    });

    let column = {
      title: value.target.value,
      dataIndex: value.target.value,
      width: '100',
      maxWidth: '200',
    };
    columnsRef.value.splice(columnsRef.value.length - 9, 0, column);
    // 计算笛卡尔积
    showAddSkuButtonFunc();
  }
  // 添加sku按钮显示隐藏
  function showAddSkuButtonFunc() {
    showAddSkuButton.value = true;
  }
  function hideAddSkuButtonFunc() {
    showAddSkuButton.value = false;
  }
  // sku的规格标签关闭（删除一个sku的规格）
  const handleClose = (sku: Sku, removedTag: string) => {
    let tags = sku.item;
    tags = tags.filter((tag) => tag !== removedTag);
    sku.item = tags;
  };
  // 动态添加sku规格---------------------------------------------------------------------------------------
  const handleInputConfirm = (sku: SkuControl) => {
    const inputValue = sku.inputValue;
    let tags = sku.item;
    if (inputValue && tags.indexOf(inputValue) === -1) {
      tags = [...tags, inputValue];
    }
    sku.item = tags;
    sku.inputVisible = false;
  };
  // 展示添加新的sku项目的输入框
  const showInput = (sku: SkuControl) => {
    sku.inputVisible = true;
  };
  // 笛卡尔积表格---------------------------------------------------------------------------------------
  // 基础表头
  const columns = [
    {
      title: '销售价',
      dataIndex: 'price',
      width: '5%',
    },
    {
      title: '成本价',
      dataIndex: 'costPrice',
      width: '5%',
    },
    {
      title: '划线价',
      dataIndex: 'linePrice',
      width: '5%',
    },
    {
      title: '库存',
      dataIndex: 'stock',
      width: '5%',
    },
    {
      title: '描述',
      dataIndex: 'description',
      width: '20%',
    },
    {
      title: '库存告警',
      dataIndex: 'warnStock',
      width: '5%',
    },
    {
      title: '是否上架',
      dataIndex: 'status',
      width: '10%',
    },
    {
      title: 'sku编码',
      dataIndex: 'skuCode',
      width: '10%',
    },
    {
      title: 'image',
      dataIndex: 'image',
      width: '20%',
    },
  ];
  const columnsRef = ref(columns);

  export interface SkuTableBaseItem {
    key: string;
    costPrice: number;
    price: number;
    linePrice: number;
    stock: number;
    description: string;
    warnStock: boolean;
    skuCode: string;
    status: 'ON_SHELVES' | 'OFF_SHELVES';
    image: UploadCallBack[];
  }

  // 表格数据ref
  const data: SkuTableBaseItem[] = [];
  const dataSource = ref(data);

  type SkuCombination = {
    [key: string]: string;
  };

  // 笛卡尔积生成方法
  function generateCombinations(skus: Sku[]): SkuCombination[] {
    if (skus.length === 0) {
      return [{}]; // 空数组返回包含一个空对象的数组
    }

    const [first, ...rest] = skus;
    const combinations: SkuCombination[] = [];

    // 生成剩余SKU的笛卡尔积
    const subCombinations = generateCombinations(rest);
    // 遍历当前SKU的所有选项
    for (const item of first.item.length == 0 ? [''] : first.item) {
      // 对于每个剩余SKU的笛卡尔积，添加当前SKU的选项
      if (subCombinations.length != 0) {
        for (const combo of subCombinations) {
          const newCombo: SkuCombination = { ...combo };
          newCombo[first.name] = item;
          combinations.push(newCombo);
        }
      } else {
        combinations.push({ [first.name]: item });
      }
    }
    return combinations;
  }

  // 监听sku数据变化，渲染sku表格
  watchDeep(skus, () => {
    let skuCombinations = generateCombinations(toRaw(skus));
    dataSource.value.splice(0, dataSource.value.length);
    skuCombinations.forEach((skuCombination, index) => {
      dataSource.value.push({
        key: index.toString(),
        price: 0,
        costPrice: 0,
        linePrice: 0,
        stock: 0,
        description: '',
        image: [],
        warnStock: true,
        skuCode: '',
        status: 'ON_SHELVES',
        ...skuCombination,
      });
    });
    sku_selected('sku:changed', toRaw(dataSource.value));
  });
  // -------------------------------------------------------------------------------------------
  const sku_selected = defineEmits(['sku:changed']);
</script>
